package com.base.util;

import com.base.util.intfac.ParseUtilConvert;
import org.apache.log4j.Logger;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by dell on 2017/8/23.
 */
public class BeanCopyUtil {

    private static Logger logger = Logger.getLogger(BeanCopyUtil.class);

    /**
     * 通过setter和getter将obj1复制给obj2
     * 不能级联操作
     * @param obj1
     * @param obj2
     */
    public static void copyByMethod(Object obj1,Object obj2,ParseUtilConvert pc) throws Exception{
        List<Field> listField = getAllField(obj2.getClass());
        if(listField != null && !listField.isEmpty()){
            listField.stream().forEach(o->{
                try{
                    setValueBySetter(obj2,o.getName(),getValueByGetter(obj1,o.getName()),pc);
                }catch(Exception e){e.printStackTrace();}
            });
        }
    }

    /**
     * 将obj1复制给obj2
     * 不能级联操作
     * @param obj1
     * @param obj2
     */
    public static void copy(Object obj1,Object obj2,ParseUtilConvert pc) throws Exception{
        List<Field> listField = getAllField(obj2.getClass());
        if(listField != null && !listField.isEmpty()){
            listField.stream().forEach(o->{
                try{
                    setValue(obj2,o.getName(),getValue(obj1,o.getName()),pc);
                }catch(Exception e){logger.info(e.getMessage());e.printStackTrace();}
            });
        }
    }

    /**
     * 获取类所有属性
     * @param clazz 类
     * @return
     */
    public static List<Field> getAllField(Class<?> clazz){
        List<Field> list = new ArrayList<>();
        Field []fields = clazz.getDeclaredFields();
        if(fields != null && fields.length > 0){
            for(Field f:fields){
                list.add(f);
            }
        }
        Class<?> parentClass = clazz.getSuperclass();
        if(parentClass != null){
            list.addAll(getAllField(parentClass));
        }
        return list;
    }


    /**
     * 获取所有方法
     * @param clazz 类
     * @return
     */
    public static List<Method> getAllMethod(Class<?> clazz){
        List<Method> list = new ArrayList<>();
        Method []methods = clazz.getDeclaredMethods();
        if(methods != null && methods.length > 0){
            for(Method m:methods){
                list.add(m);
            }
        }
        Class<?> parentClass = clazz.getSuperclass();
        if(parentClass != null){
            list.addAll(getAllMethod(parentClass));
        }
        return list;
    }

    /**
     * 根据get方法获取对象属性值
     * @param obj
     * @param fieldName
     * @return
     */
    public static Object getValueByGetter(Object obj,String fieldName) throws Exception{
        List<Method> listMethods = getAllMethod(obj.getClass());
        if(listMethods!=null && !listMethods.isEmpty()){
            Method method = listMethods.stream().filter(m->m.getName().equals("get"+fieldName.substring(0,1).toUpperCase()+fieldName.substring(1))||m.getName().equals("is"+fieldName.substring(0,1).toUpperCase()+fieldName.substring(1))).findFirst().get();
            if(method != null){
                return method.invoke(obj,null);
            }
        }
        throw new Exception("属性名为"+fieldName+"的get方法不存在！");
    }

    /**
     * 根据set方法设置属性值
     * @param obj
     * @param fieldName
     */
    public static void setValueBySetter(Object obj,String fieldName,Object value,ParseUtilConvert pc) throws Exception{
        List<Method> listMethods = getAllMethod(obj.getClass());
        if(listMethods!=null && !listMethods.isEmpty()){
            Method method = listMethods.stream().filter(m->m.getName().equals("set"+fieldName.substring(0,1).toUpperCase()+fieldName.substring(1))).findFirst().get();
            if(method != null){
                Field field = obj.getClass().getField(fieldName);
                if(field == null){
                    throw new Exception(fieldName+"属性未找到");
                }
                method.invoke(obj,ParseUtil.parse(value,field.getType(),pc));
            }
        }
        throw new Exception("属性名为"+fieldName+"的set方法不存在！");
    }

    /**
     * 直接获取属性值
     * @param obj
     * @param fieldName
     * @return
     */
    public static Object getValue(Object obj,String fieldName) throws Exception{
        List<Field> listFields = getAllField(obj.getClass());
        if(listFields == null || listFields.isEmpty()){
            throw new Exception("对象无属性");
        }
        Field field = listFields.stream().filter(f->f.getName().equals(fieldName)).findFirst().get();
        if(field == null){
            throw new Exception(fieldName+"属性未找到");
        }
        boolean acc = field.isAccessible();
        if(!acc){
            field.setAccessible(true);
        }
        Object value = field.get(obj);
        if(!acc){
            field.setAccessible(false);
        }
        return value;
    }

    /**
     * 直接设置属性值
     * @param obj
     * @param fieldName
     */
    public static void setValue(Object obj,String fieldName,Object value,ParseUtilConvert pc) throws Exception{
        List<Field> listFields = getAllField(obj.getClass());
        if(listFields == null || listFields.isEmpty()){
            throw new Exception("对象无属性");
        }
        Field field = listFields.stream().filter(f->f.getName().equals(fieldName)).findFirst().get();
        if(field == null){
            throw new Exception(fieldName+"属性未找到");
        }
        if(field.isEnumConstant()){
            return;
        }
        boolean acc = field.isAccessible();
        if(!acc){
            field.setAccessible(true);
        }
        field.set(obj,ParseUtil.parse(value,field.getType(),pc));
        if(!acc){
            field.setAccessible(false);
        }
    }

}
